package com.elvin.platform.udp;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.elvin.platform.beans.Device;
import com.elvin.platform.beans.HistoryData;
import com.elvin.platform.service.DeviceService;
import com.elvin.platform.service.HistoryDataService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Filter;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.annotation.Transformer;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.ip.dsl.Udp;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * UDP消息接收服务*/
@Configuration
@Log4j2
public class UdpServer {

  @Value("${udp.port}")
  private Integer udpPort;
  @Resource
  private HistoryDataService historyDataService;
  @Autowired
  private DeviceService deviceService;

/**
   * UDP消息接收服务写法一
   * https://docs.spring.io/spring-integration/reference/html/ip.html#inbound-udp-adapters-java-configuration
   *
   * @param
   * @return org.springframework.integration.ip.udp.UnicastReceivingChannelAdapter*/
    /*@Bean
    public UnicastReceivingChannelAdapter unicastReceivingChannelAdapter() {
        // 实例化一个UDP消息接收服务
        UnicastReceivingChannelAdapter unicastReceivingChannelAdapter = new UnicastReceivingChannelAdapter(udpPort);
        // unicastReceivingChannelAdapter.setOutputChannel(new DirectChannel());
        unicastReceivingChannelAdapter.setOutputChannelName("udpChannel");
        logger.info("UDP服务启动成功，端口号为: {}", udpPort);
        return unicastReceivingChannelAdapter;
    }*/

  /**
   * UDP消息接收服务写法二
   * https://docs.spring.io/spring-integration/reference/html/ip.html#inbound-udp-adapters-java-dsl-configuration
   *
   * @param
   * @return org.springframework.integration.dsl.IntegrationFlow*/
  @Bean
  public IntegrationFlow integrationFlow() {
    log.info("UDP服务启动成功，端口号为: {}", udpPort);
    return IntegrationFlows.from(Udp.inboundAdapter(udpPort)).channel("udpChannel").get();
  }


  /**
   * 转换器
   *
   * @param payload
  　　* @param headers
   * @return java.lang.String*/
  @Transformer(inputChannel = "udpChannel", outputChannel = "udpFilter")
  public String transformer(@Payload byte[] payload, @Headers Map<String, Object> headers) {
    String byte2Hex = byte2Hex(payload);
    log.info("转换为16进制的字符串："+byte2Hex);
    return byte2Hex;
  }

  /**
   *  将byte[]数组转换成16进制字符。一个byte生成两个字符，长度对应1:2
   * @param bytes，输入byte[]数组
   * @return 16进制字符
   */
  public static String byte2Hex(byte[] bytes) {
    if (bytes == null) {
      return null;
    }
    StringBuilder builder = new StringBuilder();
    // 遍历byte[]数组，将每个byte数字转换成16进制字符，再拼接起来成字符串
    for (int i = 0; i < bytes.length; i++) {
      // 每个byte转换成16进制字符时，bytes[i] & 0xff如果高位是0，输出将会去掉，所以+0x100(在更高位加1)，再截取后两位字符
      builder.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
    }
    return builder.toString();
  }
  /**
   * 过滤器*/
  @Filter(inputChannel = "udpFilter", outputChannel = "udpRouter")
  public boolean filter(String message, @Headers Map<String, Object> headers) {
    // 获取来源Id
    String id = headers.get("id").toString();
    // 获取来源IP，可以进行IP过滤
    String ip = headers.get("ip_address").toString();
    // 获取来源Port
    String port = headers.get("ip_port").toString();
    // 信息数据过滤
      /*if (message.indexOf("-") < 0) {
          // 没有-的数据会被过滤
          return false;
      }*/
    return true;
  }

  /**
   * 路由分发处理器*/
  @Router(inputChannel = "udpRouter")
  public String router(String message, @Headers Map<String, Object> headers) {
    // 获取来源Id
    String id = headers.get("id").toString();
    // 获取来源IP，可以进行IP过滤
    String ip = headers.get("ip_address").toString();
    // 获取来源Port
    String port = headers.get("ip_port").toString();
    // 筛选，走那个处理器
    if (false) {
      return "udpHandle2";
    }
    return "udpHandle1";
  }

  /**
   * 最终处理器1*/
  @ServiceActivator(inputChannel = "udpHandle1")
  public void udpMessageHandle(String message) throws Exception {
    // 可以进行异步处理
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    log.info("udp接收到的数据message："+message);
    String devId = null;
    String reportData = null;
    try {
      devId = message.substring(6, 18);
      reportData = message.substring(32, 40);
    } catch (Exception e) {
      throw new Exception("请检查数据格式");
    }
    log.info("设备id{},设备数据{}：",devId,reportData);
    if(devId.length()>0){
      EntityWrapper<Device> wrapper = new EntityWrapper<>();
      wrapper.eq("dev_id", devId);
      Device device = deviceService.selectOne(wrapper);
      if(device!=null){
        String dateStr = formatter.format(new Date());
        //log.info("查询到的数据是"+device.toString());
        device.setReport1(reportData);
        device.setUpdateTime(formatter.parse(dateStr));
        //更新设备表
        deviceService.updateById(device);
        HistoryData historyData = new HistoryData();
        historyData.setDevId(devId);
        historyData.setReportDate(formatter.parse(dateStr));
        historyData.setDataSources("UDP_CO2");
        historyData.setReport(reportData);
        //log.info("插入历史表的数据是"+historyData.toString());
        //插入历史表
        historyDataService.insert(historyData);
      }
    }
  }

  /**
   * 最终处理器2*/
  @ServiceActivator(inputChannel = "udpHandle2")
  public void udpMessageHandle2(String message) throws Exception {
    log.info("UDP2:" + message);
  }
}


